home *** CD-ROM | disk | FTP | other *** search
/ Developer CD Series 2000 August: Tool Chest / Dev.CD Aug 00 TC Disk 2.toast / pc / sample code / quicktime / timecodes / qttimecode / common files / winframework.c < prev    next >
Encoding:
C/C++ Source or Header  |  2000-06-23  |  61.6 KB  |  2,121 lines

  1. //////////
  2. //
  3. //    File:        WinFramework.c
  4. //
  5. //    Contains:    Basic support for playing QuickTime and QuickTime VR movies in a Windows application.
  6. //                WinFramework is a simple QuickTime viewer and editor framework. It handles windows,
  7. //                menus, messages, and other low-level things. Put your application-specific code into
  8. //                the file ComApplication.c (or other files).
  9. //
  10. //    Written by:    Tim Monroe
  11. //                Based on MDIPlayer sample code by Brian S. Friedkin (Aug 5, 1996).
  12. //
  13. //    Copyright:    © 1997-1999 by Apple Computer, Inc., all rights reserved.
  14. //
  15. //    Change History (most recent first):
  16. //
  17. //       <50>         06/07/99    rtm        added GetFrontAppWindow and GetNextAppWindow; tweaked AdjustMenus
  18. //       <49>         06/05/99    rtm        added gAppFSSpec to keep track of the application's location
  19. //       <48>         05/12/99    rtm        tweaked DoSaveAsMovieWindow to ensure it creates single-fork movies; renamed it
  20. //                                    as DoSaveAsMovieFile
  21. //       <47>         05/11/99    rtm        further work on DoSaveAsMovieWindow
  22. //       <46>         05/10/99    rtm        commented CloseMovieFile out of DoCreateMovieWindow; tweaked DoUpdateMovieFile
  23. //                                    and DoSaveAsMovieWindow to reflect changes
  24. //       <45>         04/02/99    rtm        added default name for new movies; added DoSaveAsMovieWindow to implement
  25. //                                    correct "Save As" behavior; added SetWindowTitleFromFSSpec; tweaked
  26. //                                    GetDisplayName to handle case when file doesn't exist yet
  27. //       <44>         03/18/99    rtm        added SetMoviePlayHints call in DoCreateMovieWindow to support possible
  28. //                                    dynamic resizing of streamed movies
  29. //       <43>         02/01/99    rtm        added Save As menu command to basic shell
  30. //       <42>         11/02/98    rtm        made changes to compile with CodeWarrior IDE 3.1: WinMain takes HINSTANCE;
  31. //                                       reworked DoCreateMovieWindow to take movie name from the FSSpec when
  32. //                                    a movie is passed in
  33. //       <41>         10/20/98    rtm        added default progress procedure for all movies (in DoCreateMovieWindow)
  34. //       <40>         10/15/98    rtm        added autostarting for streamed movies
  35. //       <39>         05/18/98    rtm        renamed DoSaveMovie to DoUpdateMovieFile, to mirror MacFramework.c
  36. //       <38>         05/06/98    rtm        added CheckQuickTimeRegistration call to WinMain
  37. //       <37>         03/19/98    rtm        added !IsIconic(theWnd) before call to MCIsPlayerEvent in MovieWndProc
  38. //                                    to fix drawing problems when arranging icons; added DoApplicationEventLoopAction
  39. //                                    call to MovieWndProc
  40. //       <36>         03/18/98    rtm        added !IsIconic(theWnd) to test in WM_SIZE message processing in MovieWndProc
  41. //                                    to fix sizing problems when minimized; added WM_WINDOWPOSCHANGED processing to
  42. //                                    MovieWndProc to stop movies from playing in minimized windows
  43. //       <35>         03/16/98    rtm        fixed DoOpenCommandLineMovies
  44. //       <34>         03/14/98    rtm        added NativePathNameToFSSpec call to WinMain; changed OpenResFile to FSpOpenResFile
  45. //       <33>         02/28/98    rtm        removed call to DoApplicationEventLoopAction from main message loop
  46. //       <32>         02/13/98    rtm        added GetWindowWidth; reworked SizeWindowToMovie to call it
  47. //       <31>         02/09/98    rtm        added GetWindowReferenceFromPort
  48. //       <30>         02/06/98    rtm        added code to open the application's resource file (see WinMain);
  49. //                                    removed WM_MDIACTIVATE and WM_MOUSEACTIVATE handling from MovieWndProc
  50. //       <29>         02/02/98    rtm        added SetMenuState
  51. //       <28>         01/06/98    rtm        added WM_ACTIVATE handling to FrameWndProc, and added both WM_MDIACTIVATE
  52. //                                    and WM_MOUSEACTIVATE handling to MovieWndProc
  53. //       <27>         12/18/97    rtm        added QuitFramework, to mirror MacFramework.c
  54. //       <26>         12/12/97    rtm        added WM_MOUSEMOVE processing to MovieWndProc
  55. //       <25>         12/11/97    rtm        added GetDisplayName; finished reworking DoCreateMovieWindow
  56. //       <24>         12/10/97    rtm        started reworking DoCreateMovieWindow
  57. //       <23>         12/09/97    rtm        added DoOpenCommandLineMovies to handle movies dropped onto application icon
  58. //       <22>         12/08/97    rtm        added DoCautionAlert; finished support for Save; added Select All to Edit menu;
  59. //                                    added call to SHAddToRecentDocs in DoCreateMovieWindow
  60. //       <21>         12/05/97    rtm        added fDirty flag to window object; begun supporting Save and Save As
  61. //       <20>         12/03/97    rtm        fixed centering of Open File dialog box; see DialogProc
  62. //       <19>         11/06/97    rtm        fixed SizeWindowToMovie (now QT windows hide controller bar correctly)
  63. //       <18>         11/05/97    rtm        removed DoIdleProcessing; fixed bugs in DoCreateMovieWindow, AdjustMenus
  64. //       <17>         11/04/97    rtm        added HandleApplicationMenu call to FrameWndProc
  65. //       <16>         10/30/97    rtm        added GetPortFromWindowReference
  66. //       <15>         10/24/97    rtm        simplified SizeWindowToMovie, following latest MDIPlayer.c; removed
  67. //                                    GetWindowBorderWidth and GetWindowBorderHeight (called only by SizeWindowToMovie)
  68. //       <14>         10/23/97    rtm        moved InitializeQTVR and TerminateQTVR to ComApplication.c
  69. //       <13>         10/16/97    rtm        removed idle timer; removed MyGetMessage (QT emits idle events, eh?)
  70. //       <12>         10/14/97    rtm        upgraded to latest header files
  71. //       <11>         09/18/97    rtm        added GetFrontWindow and GetNextWindow; added gIdleTimer to emit idles
  72. //       <10>         09/15/97    rtm        added INIT_QTVR and TERM_QTVR to WinMain
  73. //       <9>         09/10/97    rtm        added MyGetMessage to send WM_IDLE messages when no messages are in queue;
  74. //                                    used EnumChildWindows to process idle messages for all movie windows
  75. //       <8>         09/10/97    rtm        changed DoOpenMovie into DoCreateMovieWindow and SetupMovieWindowWithController
  76. //                                    (based on functions of same names in VRShell's MacFramework.c)
  77. //       <7>         09/08/97    rtm        conditionalized code for creating grow box
  78. //       <6>         08/22/97    rtm        added code to DialogProc to center dialog boxes (from SimplePlayerSDI);
  79. //                                    factored out GetFile from DoOpenMovie; rewrote DoIdleProcessing
  80. //       <5>         08/21/97    rtm        changed child windows' icon spec to NULL; added WM_CLOSE case to DialogProc;
  81. //                                    added hooks for WinApplication.c; added GetAppDataFromFrontWindow et al.
  82. //       <4>         08/20/97    rtm        removed "CALLBACK" from declaration of ApplicationMCActionFilterProc and
  83. //                                    changed return type to Boolean; seems to fix some QuickTime movie problems;
  84. //                                    added GetMessagePos and GetMessageTime to event handling
  85. //       <3>         08/18/97    rtm        removed "&& gNumWindowsOpen" test from WM_INITMENU in FrameWndProc;
  86. //                                    added LOWORD stripping to WM_COMMAND switches (accelerators were being lost)
  87. //       <2>         07/03/97    rtm        made changes to compile with latest QT3.0 headers;
  88. //                                    ported to CodeWarrior IDE version 2.0
  89. //       <1>         07/02/97    rtm        first file; revised to personal coding style
  90. //       
  91. //////////
  92.  
  93. // application header files
  94. #include "WinFramework.h"
  95. #include "ComResource.h"
  96.  
  97. // Windows header files
  98. #include <shlobj.h>                                        // for SHAddToRecentDocs
  99.  
  100. // C runtime header files
  101. #include <stdlib.h>
  102. #include <malloc.h>
  103.  
  104. // global variables
  105. Rect                gLimitRect = {10, 10, 480, 640};    // max size for any window
  106.  
  107. BOOL                gShuttingDown = false;                // flag that keeps track of termination state
  108. HANDLE                ghInst;                                // the instance of this application
  109. HWND                ghWnd;                                // the MDI frame window; this window has the menu bar
  110. HWND                ghWndMDIClient;                     // the MDI client window
  111.  
  112. char                gChildName[] = "QTShellChild";
  113. char                gMovieType[] = "QuickTime Movie";
  114. Rect                gMCResizeBounds;
  115. BOOL                gShowGrowBox = true;
  116. int                    gNumWindowsOpen = 0;
  117. BOOL                gWeAreSizingWindow = false;
  118. BOOL                gWeAreCreatingWindow = false;
  119.  
  120. short                 gAppResFile = kInvalidFileRefNum;    // file reference number for this application's resource file
  121. FSSpec                gAppFSSpec;                            // file specification for the application itself
  122.  
  123. char                gAppName[20];                        // the name of this application
  124. LPSTR                gCmdLine;                            // the command line passed to WinMain
  125.  
  126. ModalFilterUPP        gModalFilterUPP = NULL;                // UPP to our custom dialog event filter
  127.  
  128.  
  129. //////////
  130. //
  131. // WinMain
  132. // The main function for this application.
  133. //
  134. //////////
  135.  
  136. int CALLBACK WinMain (HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR theCmdLine, int nCmdShow)
  137. {
  138.     HANDLE                myAccel;
  139.     HWND                myWindowFrame;
  140.     MSG                    myMsg;
  141.     WNDCLASSEX            myWC;
  142.     char                myFileName[MAX_PATH];
  143.     DWORD                myLength;
  144.  
  145.     ghInst = hInstance;
  146.     gCmdLine = theCmdLine;
  147.     
  148.     if (hPrevInstance == NULL) {
  149.         LoadString(hInstance, IDS_APPNAME, gAppName, sizeof(gAppName));
  150.         
  151.         // register the frame window class
  152.         myWC.cbSize        = sizeof(WNDCLASSEX);
  153.         myWC.style         = CS_HREDRAW | CS_VREDRAW;
  154.         myWC.lpfnWndProc   = (WNDPROC)FrameWndProc;
  155.         myWC.cbClsExtra    = 0;
  156.         myWC.cbWndExtra    = 0;
  157.         myWC.hInstance     = hInstance;
  158.         myWC.hIcon         = LoadIcon(hInstance, MAKEINTRESOURCE(IDI_APPICON));
  159.         myWC.hCursor       = LoadCursor(NULL, IDC_ARROW);
  160.         myWC.hbrBackground = (HBRUSH)(COLOR_WINDOW + 1);
  161.         myWC.lpszMenuName  = gAppName;
  162.         myWC.lpszClassName = gAppName;
  163.         myWC.hIconSm       = LoadImage(hInstance, MAKEINTRESOURCE(IDI_APPICON), IMAGE_ICON, 16, 16, 0);
  164.                                      
  165.         if (!RegisterClassEx(&myWC)) {
  166.             if (!RegisterClass((LPWNDCLASS)&myWC.style))
  167.                 return(0);
  168.         }
  169.  
  170.         // register the movie child window class
  171.         myWC.cbSize        = sizeof(WNDCLASSEX);
  172.         myWC.style         = 0;
  173.         myWC.lpfnWndProc   = (WNDPROC)MovieWndProc;
  174.         myWC.cbClsExtra    = 0;
  175.         myWC.cbWndExtra    = 0;
  176.         myWC.hInstance     = hInstance;
  177.         myWC.hIcon         = LoadIcon(hInstance, MAKEINTRESOURCE(IDI_CHILDICON));
  178.         // to avoid having QuickTime VR "fight" with the system over the cursor,
  179.         // we set the client area cursor to NULL; this means that for QuickTime
  180.         // movies, we'll need to change the cursor to an arrow manually; see the
  181.         // handling of the WM_MOUSEMOVE message in MovieWndProc
  182.         myWC.hCursor       = NULL;
  183.         myWC.hbrBackground = (HBRUSH)(COLOR_WINDOW + 1);
  184.         myWC.lpszMenuName  = NULL;
  185.         myWC.lpszClassName = gChildName;
  186.         myWC.hIconSm       = LoadImage(hInstance, MAKEINTRESOURCE(IDI_CHILDICON), IMAGE_ICON, 16, 16, 0);
  187.                                      
  188.         if (!RegisterClassEx(&myWC)) {
  189.             if (!RegisterClass((LPWNDCLASS)&myWC.style))
  190.                 return(0);
  191.         }
  192.     }
  193.  
  194.     // load accelerators
  195.     myAccel = LoadAccelerators(hInstance, gAppName);
  196.  
  197.     // initialize QuickTime Media Layer
  198.     InitializeQTML(0L);
  199.     
  200.     // initialize QuickTime
  201.     EnterMovies();
  202.     
  203.     // get the application's resource file, if it exists
  204.     myLength = GetModuleFileName(NULL, myFileName, MAX_PATH);        // NULL means: the current process
  205.     if (myLength != 0) {
  206.         NativePathNameToFSSpec(myFileName, &gAppFSSpec, kFullNativePath);
  207.  
  208.         gAppResFile = FSpOpenResFile(&gAppFSSpec, fsRdWrPerm);
  209.         if (gAppResFile != kInvalidFileRefNum)
  210.             UseResFile(gAppResFile);
  211.     }
  212.  
  213.     // do any application-specific initialization that must occur before the frame window is created
  214.     InitApplication(kInitAppPhase_BeforeCreateFrameWindow);
  215.     
  216.     // create the main frame window
  217.     myWindowFrame = CreateWindow(gAppName, gAppName, WS_OVERLAPPEDWINDOW | WS_CLIPCHILDREN,
  218.                                        CW_USEDEFAULT, 
  219.                                        CW_USEDEFAULT,
  220.                                      CW_USEDEFAULT, 
  221.                                      CW_USEDEFAULT,
  222.                                      NULL, 
  223.                                      NULL, 
  224.                                      hInstance, 
  225.                                      NULL);
  226.     ghWnd = myWindowFrame;
  227.     
  228.     // make sure we got a frame window
  229.     if (myWindowFrame == NULL)
  230.         return(0);
  231.         
  232.     // show the window
  233.     ShowWindow(myWindowFrame, nCmdShow);
  234.     UpdateWindow(myWindowFrame);
  235.     
  236.     // do any application-specific initialization that must occur after the frame window is created
  237.     InitApplication(kInitAppPhase_AfterCreateFrameWindow);
  238.     
  239.     // process messages
  240.     while (GetMessage(&myMsg, NULL, 0, 0)) {    
  241.         if (!TranslateMDISysAccel(ghWndMDIClient, &myMsg)) {
  242.             if (!TranslateAccelerator(myWindowFrame, myAccel, &myMsg)) {
  243.                 TranslateMessage(&myMsg);
  244.                 DispatchMessage(&myMsg);
  245.             }
  246.         }
  247.     }
  248.  
  249.     // close the application's resource file, if it was previously opened
  250.     if (gAppResFile != kInvalidFileRefNum)
  251.         CloseResFile(gAppResFile);
  252.  
  253.     // terminate the QuickTime Media Layer
  254.     ExitMovies();
  255.     TerminateQTML();
  256.  
  257.     return(myMsg.wParam);            // returns the value from PostQuitMessage
  258. }
  259.  
  260.  
  261. //////////
  262. //
  263. // FrameWndProc
  264. // The window procedure for the MDI frame window.
  265. //
  266. //////////
  267.  
  268. LRESULT CALLBACK FrameWndProc (HWND theWnd, UINT theMessage, UINT wParam, LONG lParam)
  269. {
  270.     HWND                   myChild;
  271.  
  272.     switch (theMessage) {
  273.     
  274.         case WM_CREATE: {
  275.             CLIENTCREATESTRUCT        myClientStruct = {0};
  276.  
  277.             myClientStruct.hWindowMenu  = GetSubMenu(GetMenu(theWnd), WINDOWMENU);
  278.             myClientStruct.idFirstChild = IDM_WINDOWCHILD;
  279.             
  280.             // create the MDI client filling the client area
  281.             ghWndMDIClient = CreateWindow("mdiclient",
  282.                                          NULL,
  283.                                          WS_CHILD | WS_CLIPCHILDREN | WS_VSCROLL | WS_HSCROLL,
  284.                                          0, 0, 0, 0,
  285.                                          theWnd,
  286.                                          (HMENU)0xCAC,
  287.                                          ghInst,
  288.                                          (LPVOID)&myClientStruct);
  289.             
  290.             // set initial menu state
  291.             AdjustMenus(NULL, GetMenu(theWnd));
  292.             
  293.             if (ghWndMDIClient != NULL)
  294.                 ShowWindow(ghWndMDIClient, SW_SHOW);
  295.             
  296.             return(0);
  297.         }
  298.  
  299.         case WM_ACTIVATE:
  300.             // the MDI frame window is being activated or deactivated;
  301.             // activate or deactivate any active child window by sending this message to DefMDIChildProc 
  302.             myChild = (HWND)SendMessage(ghWndMDIClient, WM_MDIGETACTIVE, 0, 0L);
  303.             if (IsWindow(myChild))
  304.                 SendMessage(myChild, WM_ACTIVATE, wParam, lParam);
  305.             break;
  306.  
  307.         case WM_COMMAND: {
  308.  
  309.             switch (LOWORD(wParam)) {
  310.                 case IDM_FILENEW:
  311.                     DoCreateNewMovie();
  312.                     break;
  313.  
  314.                 case IDM_FILEOPEN:
  315.                     DoCreateMovieWindow(NULL, NULL);
  316.                     break;
  317.  
  318.                 case IDM_FILESAVE:
  319.                 case IDM_FILESAVEAS:
  320.                     // save the active child window
  321.                     myChild = (HWND)SendMessage(ghWndMDIClient, WM_MDIGETACTIVE, 0, 0L);
  322.                     if (IsWindow(myChild))
  323.                         SendMessage(myChild, WM_COMMAND, wParam, lParam);
  324.                     return(0);
  325.  
  326.                 case IDM_FILECLOSE:
  327.                     // close the active child window
  328.                     myChild = (HWND)SendMessage(ghWndMDIClient, WM_MDIGETACTIVE, 0, 0L);
  329.                     if (IsWindow(myChild))
  330.                         SendMessage(myChild, WM_CLOSE, 0L, 0L);
  331.                     return(0);
  332.  
  333.                 case IDM_EXIT:
  334.                     // set our global flag to indicate we're shutting down
  335.                     gShuttingDown = true;
  336.                     
  337.                     // do application-specific processing that must occur before movie windows are closed
  338.                     StopApplication(kStopAppPhase_BeforeDestroyWindows);
  339.                     
  340.                     // close all open movie windows;
  341.                     // note that the user can cancel the shutting down
  342.                     SendMessage(theWnd, WM_COMMAND, (WPARAM)IDM_WINDOWCLOSEALL, 0L);
  343.                     
  344.                     // close the frame window, if we're still shutting down
  345.                     if (gShuttingDown)
  346.                         SendMessage(theWnd, WM_CLOSE, 0, 0L);
  347.                         
  348.                     return(0);
  349.  
  350.                 case IDM_WINDOWTILE:
  351.                     SendMessage(ghWndMDIClient, WM_MDITILE, 0, 0L);
  352.                     return(0);
  353.  
  354.                 case IDM_WINDOWCASCADE:
  355.                     SendMessage(ghWndMDIClient, WM_MDICASCADE, 0, 0L);
  356.                     return(0);
  357.  
  358.                 case IDM_WINDOWICONS:
  359.                     SendMessage(ghWndMDIClient, WM_MDIICONARRANGE, 0, 0L);
  360.                     return(0);
  361.  
  362.                 case IDM_WINDOWCLOSEALL: {
  363.                     WindowReference        myWindow, myNextWindow;
  364.             
  365.                     // walk the window list and destroy any open windows
  366.                     myWindow = GetFrontMovieWindow();
  367.                     while (myWindow != NULL) {
  368.                         myNextWindow = GetNextMovieWindow(myWindow);
  369.                         SendMessage(myWindow, WM_CLOSE, 0L, 0L);
  370.                         myWindow = myNextWindow;
  371.                     }
  372.                     
  373.                     return(0);
  374.                 }
  375.  
  376.                 case IDM_ABOUT:
  377.                     ShowAboutBox();
  378.                     return(0);
  379.  
  380.                 default:                
  381.                     // pass this message to the active child window...
  382.                     myChild = (HWND)SendMessage(ghWndMDIClient, WM_MDIGETACTIVE, 0, 0L);
  383.                     if (IsWindow(myChild))
  384.                         SendMessage(myChild, WM_COMMAND, wParam, lParam);
  385.  
  386.                     // ...then do any application-specific menu handling, if no movie windows are open...
  387.                     if (myChild == NULL)
  388.                         HandleApplicationMenu((UInt16)LOWORD(wParam));
  389.                     
  390.                     // ...and then pass it to DefFrameProc
  391.                     break;
  392.             }
  393.             break;
  394.         }
  395.  
  396.         case WM_OPENDROPPEDFILES:
  397.             // open any movie files that were dropped onto the application icon
  398.             DoOpenCommandLineMovies(gCmdLine);
  399.             return(0);
  400.  
  401.         case WM_INITMENU:
  402.             if (GetMenu(theWnd) == (HMENU)wParam)
  403.                 return(AdjustMenus((HWND)SendMessage(ghWndMDIClient, WM_MDIGETACTIVE, 0, 0L), (HMENU)wParam));
  404.             return(1);
  405.  
  406.         case WM_CLOSE:
  407.             // if we're not already in the process of shutting down,
  408.             // simulate the selection of the Quit menu command
  409.             if (!gShuttingDown) {
  410.                 SendMessage(ghWnd, WM_COMMAND, IDM_EXIT, 0L);
  411.                 return(0);
  412.             }
  413.             break;
  414.             
  415.         case WM_DESTROY:
  416.             // do any application-specific shutdown
  417.             StopApplication(kStopAppPhase_AfterDestroyWindows);
  418.             PostQuitMessage(0);
  419.             break;
  420.     }
  421.     
  422.     return(DefFrameProc(theWnd, ghWndMDIClient, theMessage, wParam, lParam));
  423. }
  424.  
  425.  
  426. //////////
  427. //
  428. // MovieWndProc
  429. // The window procedure for a movie window.
  430. //
  431. //////////
  432.  
  433. LRESULT CALLBACK MovieWndProc (HWND theWnd, UINT theMessage, UINT wParam, LONG lParam)
  434. {
  435.     WPARAM                myWidth, myHeight;
  436.     MovieController        myMC = NULL;
  437.     Movie                myMovie = NULL;
  438.     WindowObject        myWindowObject = NULL;
  439.     MSG                    myMsg = {0};
  440.  
  441.     // get the window object, movie, and movie controller for this window
  442.     myWindowObject = GetWindowObjectFromWindow(theWnd);
  443.     if (myWindowObject != NULL) {
  444.         myMC = (**myWindowObject).fController;
  445.         myMovie = (**myWindowObject).fMovie;
  446.     }
  447.  
  448.     // give the movie controller this message first
  449.     if (!gShuttingDown && myMC) {
  450.         EventRecord        myMacEvent;
  451.         LONG            myPoints = GetMessagePos();
  452.  
  453.         myMsg.hwnd = theWnd;
  454.         myMsg.message = theMessage;
  455.         myMsg.wParam = wParam;
  456.         myMsg.lParam = lParam;
  457.         myMsg.time = GetMessageTime();
  458.         myMsg.pt.x = LOWORD(myPoints);
  459.         myMsg.pt.y = HIWORD(myPoints);
  460.  
  461.         // translate a Windows event to a Mac event
  462.         WinEventToMacEvent(&myMsg, &myMacEvent);
  463.  
  464.         DoApplicationEventLoopAction(&myMacEvent);
  465.         
  466.         // pass the Mac event to the movie controller, but only if the movie window isn't minimized
  467.         if (!IsIconic(theWnd))
  468.             MCIsPlayerEvent(myMC, (EventRecord *)&myMacEvent);
  469.     }
  470.  
  471.     switch (theMessage) {
  472.         case WM_CREATE:
  473.             // create some private storage
  474.             myWindowObject = (WindowObject)NewHandleClear(sizeof(WindowObjectRecord));
  475.             if (myWindowObject != NULL) {
  476.                 (**myWindowObject).fWindow = theWnd;
  477.                 (**myWindowObject).fController = NULL;
  478.                 (**myWindowObject).fObjectType = kMovieControllerObject;
  479.                 (**myWindowObject).fInstance = NULL;
  480.                 (**myWindowObject).fAppData = NULL;
  481.             }
  482.  
  483.             SetWindowLong(theWnd, GWL_USERDATA, (LPARAM)myWindowObject);
  484.  
  485.             // associate a GrafPort with this window and set the port
  486.             CreatePortAssociation(theWnd, NULL, 0L);
  487.             MacSetPort(GetPortFromWindowReference(theWnd));
  488.             break;
  489.  
  490.         case WM_WINDOWPOSCHANGING:
  491.             // don't show the window until we have created a movie and
  492.             // can therefore properly size the window to contain the movie
  493.             if (gWeAreCreatingWindow) {
  494.                 WINDOWPOS    *lpWindowPos = (WINDOWPOS*)lParam;
  495.                 
  496.                 lpWindowPos->flags &= ~SWP_SHOWWINDOW;
  497.             }
  498.             break;
  499.  
  500.         case WM_WINDOWPOSCHANGED:
  501.             // if a movie window has become minimized, stop the movie
  502.             if (IsIconic(theWnd))
  503.                 StopMovie(myMovie);
  504.             break;
  505.  
  506.         case WM_SIZE:
  507.             // resize the movie and controller to fit the window
  508.             myWidth = LOWORD(lParam);
  509.             myHeight = HIWORD(lParam);
  510.             
  511.             // we do NOT want to resize the movie controller if the window is minimized,
  512.             // if there is no movie controller, or if we are in the middle of resizing the window
  513.             if (!gWeAreSizingWindow && (myMC != NULL) && !IsIconic(theWnd)) {
  514.                 Rect        myRect;
  515.                 
  516.                 myRect.top = 0;
  517.                 myRect.left = 0;
  518.                 myRect.right = myWidth;
  519.                 myRect.bottom = myHeight;
  520.                 
  521.                 MCSetControllerBoundsRect(myMC, &myRect);
  522.             }
  523.             break;
  524.  
  525.         case WM_MOUSEMOVE:
  526.             // for QuickTime movies (but NOT for QuickTime VR movies), set the cursor to the arrow cursor
  527.             if (myWindowObject != NULL)
  528.                 if ((**myWindowObject).fInstance == NULL)
  529.                     SetCursor(LoadCursor(NULL, IDC_ARROW));
  530.             break;
  531.  
  532.         case WM_PUMPMOVIE:
  533.             // we receive this message only to idle the movie
  534.             break;
  535.  
  536.         case WM_CHAR:
  537.             // do any application-specific key press handling
  538.             HandleApplicationKeyPress((char)wParam);
  539.             break;
  540.  
  541.         case WM_COMMAND: {
  542.  
  543.             switch (LOWORD(wParam)) {
  544.                             
  545.                 case IDM_FILESAVE:
  546.                     DoUpdateMovieFile(theWnd);
  547.                     break;
  548.  
  549.                 case IDM_FILESAVEAS:
  550.                     DoSaveAsMovieFile(theWnd);
  551.                     break;
  552.  
  553.                 case IDM_EDITUNDO:
  554.                     DoUndo(theWnd);
  555.                     break;
  556.  
  557.                 case IDM_EDITCUT:
  558.                     DoCut(theWnd);
  559.                     break;
  560.  
  561.                 case IDM_EDITCOPY:
  562.                     DoCopy(theWnd);
  563.                     break;
  564.  
  565.                 case IDM_EDITPASTE:
  566.                     DoPaste(theWnd);
  567.                     break;
  568.  
  569.                 case IDM_EDITCLEAR:
  570.                     DoClear(theWnd);
  571.                     break;
  572.                     
  573.                 case IDM_EDITSELECTALL:
  574.                     if (myMC != NULL)
  575.                         QTUtils_SelectAllMovie(myMC);
  576.                     break;
  577.                     
  578.                 default:
  579.                     // do any application-specific menu handling
  580.                     HandleApplicationMenu((UInt16)LOWORD(wParam));
  581.                     break;
  582.             }
  583.             
  584.             break;
  585.         }    // case WM_COMMAND
  586.  
  587.         case WM_GETMINMAXINFO:
  588.             CalcWindowMinMaxInfo(theWnd, (LPMINMAXINFO)lParam);
  589.             break;
  590.  
  591.         case WM_CLOSE:
  592.             // prepare to close the window, making sure that any changed data is saved or explicitly discarded;
  593.             // we can still cancel the window closing here
  594.             if (myWindowObject != NULL) {
  595.             
  596.                 // if the window's data is "dirty", give the user a chance to save it
  597.                 if ((**myWindowObject).fDirty) {
  598.                     int            myItem;
  599.                     char        myText[256];
  600.         
  601.                     // get the title of the window
  602.                     GetWindowText(theWnd, myText, sizeof(myText));
  603.         
  604.                     // display the "Save changes" dialog box
  605.                     myItem = DoCautionAlert(theWnd, IDS_SAVEDIALOG, MB_ICONEXCLAMATION, MB_YESNOCANCEL, gAppName, myText);
  606.                     switch (myItem) {
  607.                         case kSaveChanges:
  608.                             DoUpdateMovieFile(theWnd);    // save the data in the window
  609.                             break;
  610.                             
  611.                         case kDontSaveChanges:
  612.                             break;                        // discard any unsaved changes (that is, don't do anything)
  613.                             
  614.                         case kCancelClose:
  615.                             gShuttingDown = false;        // do not close the window and do not quit the application
  616.                             return(0);
  617.                         
  618.                         default:
  619.                             return(0);                    // unexpected item selected; just return
  620.                     }
  621.                 }
  622.             } // if (myWindowObject != NULL)
  623.             
  624.             // if we got to this point, it's okay to close and destroy the window
  625.             SendMessage(ghWndMDIClient, WM_MDIDESTROY, (WPARAM)theWnd, 0L);
  626.             break;
  627.  
  628.         case WM_DESTROY:
  629.             // when we get this message,
  630.             // the window has been removed from the screen and must be destroyed; no turning back!
  631.             if (myWindowObject != NULL) {
  632.                                 
  633.                 // close the movie file
  634.                 if ((**myWindowObject).fFileRefNum != kInvalidFileRefNum) {
  635.                     CloseMovieFile((**myWindowObject).fFileRefNum);
  636.                     (**myWindowObject).fFileRefNum = kInvalidFileRefNum;
  637.                 }
  638.     
  639.                 // dispose movie and controller
  640.                 if (myMC != NULL) {
  641.                     MCSetActionFilterWithRefCon(myMC, NULL, 0);
  642.                     DisposeMovieController(myMC);
  643.                 }
  644.                 
  645.                 if (myMovie != NULL)
  646.                     DisposeMovie(myMovie);
  647.                     
  648.                 // do any application-specific window clean-up, then toss the window object
  649.                 RemoveApplicationWindowObject(myWindowObject);
  650.                 DisposeHandle((Handle)myWindowObject);
  651.             }
  652.         
  653.             SetWindowLong(theWnd, GWL_USERDATA, 0);
  654.  
  655.             // destroy the port association
  656.             DestroyPortAssociation((CGrafPtr)GetHWNDPort(theWnd));
  657.             
  658.             // decrement the count of open movie windows, if there are any
  659.             if (gNumWindowsOpen > 0)
  660.                 gNumWindowsOpen--;
  661.  
  662.             break;
  663.     }
  664.  
  665.     return(DefMDIChildProc(theWnd, theMessage, wParam, lParam));
  666. }
  667.  
  668.  
  669. //////////
  670. //
  671. // GetFile
  672. // Display the file-opening dialog box and return the name of the selected file (if any).
  673. //
  674. //////////
  675.  
  676. BOOL GetFile (char *theFileName)
  677. {
  678.     OPENFILENAME    myOFN = {0};
  679.  
  680.     // fill in the OPENFILENAME structure
  681.     memset(&myOFN, 0, sizeof(OPENFILENAME));    // first zero out the structure
  682.     *theFileName = '\0';
  683.     myOFN.lStructSize = sizeof(OPENFILENAME);
  684.     myOFN.hwndOwner = NULL;
  685.     myOFN.lpstrFile = (LPSTR)theFileName;
  686.     myOFN.nMaxFile  = 255;
  687.     myOFN.lpstrFilter  = "QuickTime Movies (*.mov) \0 *.mov\0All Files (*.*) \0 *.*\0";
  688.     myOFN.nFilterIndex = 1;
  689.     myOFN.lpstrInitialDir = NULL;
  690.     if (USEEXPLORERSTYLE)
  691.         myOFN.Flags = OFN_PATHMUSTEXIST | OFN_FILEMUSTEXIST | OFN_ENABLEHOOK | OFN_EXPLORER;
  692.     else
  693.         myOFN.Flags = OFN_PATHMUSTEXIST | OFN_FILEMUSTEXIST | OFN_ENABLEHOOK;
  694.     myOFN.lCustData = kOpenDialogCustomData;
  695.     myOFN.lpfnHook = DialogProc;
  696.  
  697.     // present the file-opening dialog
  698.     if (GetOpenFileName(&myOFN))
  699.         return(true);
  700.     else
  701.         return(false);
  702. }
  703.  
  704.  
  705. //////////
  706. //
  707. // AdjustMenus 
  708. // Adjust the application's menus.
  709. //
  710. // The theWnd parameter is a handle to the active MDI *child* window, if any.
  711. //
  712. //////////
  713.  
  714. int AdjustMenus (HWND theWnd, HMENU theMenu)
  715. {
  716.     WindowObject        myWindowObject = NULL; 
  717.     MovieController        myMC = NULL;
  718.  
  719.     if (theWnd != NULL)
  720.         myWindowObject = GetWindowObjectFromWindow(theWnd);
  721.     
  722.     if (myWindowObject != NULL)
  723.         myMC = (**myWindowObject).fController;
  724.  
  725.     // configure the edit menu
  726.     if (myMC != NULL) {
  727.         long            myFlags;
  728.  
  729.         MCGetControllerInfo(myMC, &myFlags);
  730.  
  731.         EnableMenuItem(theMenu, IDM_EDITUNDO, myFlags & mcInfoUndoAvailable ? MF_ENABLED : MF_GRAYED);
  732.         EnableMenuItem(theMenu, IDM_EDITCUT, myFlags & mcInfoCutAvailable ? MF_ENABLED : MF_GRAYED);
  733.         EnableMenuItem(theMenu, IDM_EDITCOPY, myFlags & mcInfoCopyAvailable ? MF_ENABLED : MF_GRAYED);
  734.         EnableMenuItem(theMenu, IDM_EDITPASTE, myFlags & mcInfoPasteAvailable ? MF_ENABLED : MF_GRAYED);
  735.         EnableMenuItem(theMenu, IDM_EDITCLEAR, myFlags & mcInfoClearAvailable ? MF_ENABLED : MF_GRAYED);
  736.         EnableMenuItem(theMenu, IDM_EDITSELECTALL, myFlags & mcInfoEditingEnabled ? MF_ENABLED : MF_GRAYED);
  737.     } else {
  738.         EnableMenuItem(theMenu, IDM_EDITUNDO, MF_GRAYED);
  739.         EnableMenuItem(theMenu, IDM_EDITCUT, MF_GRAYED);
  740.         EnableMenuItem(theMenu, IDM_EDITCOPY, MF_GRAYED);
  741.         EnableMenuItem(theMenu, IDM_EDITPASTE,MF_GRAYED);
  742.         EnableMenuItem(theMenu, IDM_EDITCLEAR, MF_GRAYED);
  743.         EnableMenuItem(theMenu, IDM_EDITSELECTALL, MF_GRAYED);
  744.     }
  745.     
  746.     // enable the Close item if there are any movie windows opened, else disable
  747.     if (myWindowObject != NULL)
  748.         EnableMenuItem(theMenu, IDM_FILECLOSE, (gNumWindowsOpen) ? MF_ENABLED : MF_GRAYED);
  749.     else
  750.         EnableMenuItem(theMenu, IDM_FILECLOSE, MF_GRAYED);
  751.  
  752.     // enable the Save As item if there are any movie windows opened, else disable
  753.     if (myWindowObject != NULL)
  754.         EnableMenuItem(theMenu, IDM_FILESAVEAS, (gNumWindowsOpen) ? MF_ENABLED : MF_GRAYED);
  755.     else
  756.         EnableMenuItem(theMenu, IDM_FILESAVEAS, MF_GRAYED);
  757.  
  758.     // enable the Save item if the movie window is dirty, else disable
  759.     if (myWindowObject != NULL)
  760.         EnableMenuItem(theMenu, IDM_FILESAVE, ((**myWindowObject).fDirty) ? MF_ENABLED : MF_GRAYED);
  761.     else
  762.         EnableMenuItem(theMenu, IDM_FILESAVE, MF_GRAYED);
  763.  
  764.     // adjust any application-specific menus
  765.     AdjustApplicationMenus(theWnd, theMenu);
  766.  
  767.     return(0);
  768. }
  769.  
  770.  
  771. //////////
  772. //
  773. // QuitFramework
  774. // Do any framework-specific shut-down.
  775. //
  776. //////////
  777.  
  778. void QuitFramework (void)
  779. {
  780.     // send a message to the MDI frame window telling it to close down and exit the application
  781.     SendMessage(ghWnd, WM_COMMAND, IDM_EXIT, 0L);
  782. }
  783.  
  784.  
  785. //////////
  786. //
  787. // DoCreateNewMovie
  788. // Create a new movie in a window; returns true if successful.
  789. //
  790. // NOTE: There are several user interface issues that are blissfully ignored by this routine,
  791. // principally the preferred names and the on-screen locations of the new windows. 
  792. //
  793. //////////
  794.  
  795. Boolean DoCreateNewMovie (void)
  796. {
  797.     Movie                myMovie = NULL;
  798.     FSSpec                myFSSpec;
  799.     StringPtr             myName = QTUtils_ConvertCToPascalString(kNewMovieName);
  800.     
  801.     myMovie = NewMovie(newMovieActive);
  802.     if (myMovie == NULL)
  803.         return(false);
  804.     
  805.     // create a default FSSpec
  806.     FSMakeFSSpec(0, 0L, myName, &myFSSpec);
  807.     
  808.     free(myName);
  809.     
  810.     return(DoCreateMovieWindow(myMovie, &myFSSpec));
  811. }
  812.  
  813.  
  814. //////////
  815. //
  816. // SetupMovieWindowWithController
  817. // Configure the movie controller.
  818. //
  819. //////////
  820.  
  821. MovieController SetupMovieWindowWithController (Movie theMovie, WindowReference theWindow, Boolean theMoveWindow)
  822. {
  823. #pragma unused(theMoveWindow)
  824.  
  825.     MovieController            myMC = NULL;
  826.     Rect                    myRect;
  827.     WindowObject            myWindowObject = NULL;
  828.     
  829.     if ((theMovie == NULL) || (theWindow == NULL))
  830.         return(NULL);
  831.         
  832.     myWindowObject = GetWindowObjectFromWindow(theWindow);        // get our window specific data
  833.  
  834.     // resize the movie bounding rect and offset to 0,0
  835.     GetMovieBox(theMovie, &myRect);
  836.     MacOffsetRect(&myRect, -myRect.left, -myRect.top);
  837.     SetMovieBox(theMovie, &myRect);
  838.     AlignWindow(GetHWNDPort(theWindow), false, &myRect, NULL);
  839.  
  840.     // create the movie controller
  841.     myMC = NewMovieController(theMovie, &myRect, mcTopLeftMovie);
  842.     if (myMC == NULL)
  843.         return(NULL);
  844.         
  845.     // enable the default movie controller editing
  846.     MCEnableEditing(myMC, true);
  847.         
  848.     // suppress movie badge
  849.     MCDoAction(myMC, mcActionSetUseBadge, (void *)false);
  850.  
  851.     // set the initial looping state of the movie
  852.     QTUtils_SetLoopingStateFromFile(theMovie, myMC);
  853.     
  854.     // install an action filter that does any application-specific movie controller action processing
  855.     MCSetActionFilterWithRefCon(myMC, NewMCActionFilterWithRefConProc(ApplicationMCActionFilterProc), (long)myWindowObject);
  856.  
  857.     // add grow box for the movie controller
  858.     if (gShowGrowBox) {
  859.         RECT                myRect;
  860.  
  861.         GetWindowRect(GetDesktopWindow(), &myRect);
  862.         
  863.         OffsetRect(&myRect, -myRect.left, -myRect.top);
  864.         gMCResizeBounds.top = (short)myRect.top;
  865.         gMCResizeBounds.left = (short)myRect.left;
  866.         gMCResizeBounds.right = (short)myRect.right;
  867.         gMCResizeBounds.bottom = (short)myRect.bottom;
  868.  
  869.         MCDoAction(myMC, mcActionSetGrowBoxBounds, &gMCResizeBounds);
  870.     }
  871.     
  872.     // add any application-specific controller functionality
  873.     AddControllerFunctionality(myMC);
  874.         
  875.     return(myMC);
  876. }
  877.  
  878.  
  879. //////////
  880. //
  881. // DoOpenCommandLineMovies
  882. // Parse the command line when the application first starts up and
  883. // open as movie documents any files specified on the command line.
  884. //
  885. // Based on the routine ParseCmdLinePriv in GraphicImporter.c.
  886. //
  887. //////////
  888.  
  889. void DoOpenCommandLineMovies (LPSTR theCmdLine)
  890. {
  891. #pragma unused(theCmdLine)
  892.     LPSTR                myCmdLine;
  893.     FSSpec                myFSSpec;
  894.     SHFILEINFO            myFileInfo;
  895.     
  896.     // get the command line for the current process
  897.     myCmdLine = GetCommandLine();
  898.  
  899.     // parse the command line
  900.     if (*myCmdLine) {
  901.         LPSTR            myTempLine;
  902.         
  903.         // the string preceding any white space is the name of the module (that is, the application)
  904.         myTempLine = strchr(myCmdLine, ' ');
  905.         if (myTempLine) {
  906.             myCmdLine = myTempLine;                  // skip the name of the application
  907.             while (*myCmdLine == ' ')
  908.                 myCmdLine++;                        // skip spaces to end of string or to first command
  909.  
  910.             while (*myCmdLine != '\0') {
  911.                 char     myFileName[MAX_PATH];
  912.                 char     myTempName[MAX_PATH];
  913.                 char     myBuffName[MAX_PATH];
  914.                 int     myIndex;
  915.                 
  916.                 // read thru the remaining string to find file names
  917.                 for (myIndex = 0; *myCmdLine != '\0'; myIndex++, myCmdLine++) {
  918.                     // if we encounter a space character, it might be a filename delimiter or a space in the filename;
  919.                     // we'll try to open the filename we have so far to see whether it's a valid filename; if not, the
  920.                     // space must be part of the filename we're constructing
  921.                     if (*myCmdLine == ' ') {
  922.                         HANDLE                myFindFile;
  923.                         WIN32_FIND_DATA        myFile;
  924.                     
  925.                         myTempName[myIndex] = '\0';
  926.                         strcpy(myBuffName, myTempName);
  927.                         
  928.                         myFindFile = FindFirstFile(myBuffName, &myFile);
  929.                         if (myFindFile != INVALID_HANDLE_VALUE) {
  930.                             // we found a file having the specified name; close our file search and
  931.                             // break out of our character-gobbling loop (since we've got a valid filename)
  932.                             FindClose(myFindFile);
  933.                             break;
  934.                         }
  935.                     }
  936.                 
  937.                     // if we made it here, *myCmdLine is part of the filename (possibly a space)
  938.                     myFileName[myIndex] = myTempName[myIndex] = *myCmdLine;
  939.                 }
  940.                 
  941.                 if (*myCmdLine != '\0')
  942.                     myCmdLine++;
  943.                 
  944.                 // add a terminating NULL character
  945.                 myFileName[myIndex] = '\0';
  946.  
  947.                 // make sure the filename picks out a QuickTime movie
  948.                 SHGetFileInfo(myFileName, (DWORD)0, &myFileInfo, sizeof(myFileInfo), SHGFI_TYPENAME);
  949.                 if (strcmp(myFileInfo.szTypeName, gMovieType) != 0)
  950.                     continue;
  951.                 
  952.                 // make an FSSpec record
  953.                 NativePathNameToFSSpec(myFileName, &myFSSpec, 0L);
  954.  
  955.                 // open the file in a movie window
  956.                 DoCreateMovieWindow(NULL, &myFSSpec);
  957.             }
  958.  
  959.         } else
  960.             myCmdLine += strlen(myCmdLine);           // point to NULL
  961.     }
  962. }
  963.  
  964.  
  965. //////////
  966. //
  967. // DoCreateMovieWindow
  968. // Open a movie in a new movie window; returns true if successful.
  969. //
  970. // This function is called from several places in our framework. The following combinations are possible:
  971. //    * theMovie == NULL, theFSSpec == NULL: no movie, no file; elicit a movie file from user and open it
  972. //    * theMovie != NULL, theFSSpec == NULL: new movie, no file (yet)
  973. //    * theMovie == NULL, theFSSpec != NULL: no movie, but we have an FSSpec; so just open the specified movie file
  974. //    * theMovie != NULL, theFSSpec != NULL: new movie, theFSSpec contains (at least) the movie name
  975. //
  976. //////////
  977.  
  978. BOOL DoCreateMovieWindow (Movie theMovie, FSSpec *theFSSpec)
  979. {
  980.     WindowObject        myWindowObject = NULL;
  981.     MovieController        myMC = NULL;
  982.     WindowReference        myWindow = NULL;
  983.     FSSpec                myFSSpec;
  984.     Movie                myMovie = NULL;
  985.     short                myRefNum = kInvalidFileRefNum;
  986.     short                myResID = 0;
  987.     DWORD                myVersion;
  988.     char                   myPathName[MAX_PATH];                // the full pathname of the file
  989.     char                myFileName[MAX_PATH];                // the movie file name
  990.     GrafPtr                mySavedPort;
  991.     OSErr                myErr = noErr;
  992.  
  993.     // get the current port; we may need to restore it if we cannot successfully create a new window
  994.     GetPort(&mySavedPort);
  995.  
  996.     // if we got neither a movie nor an FSSpec passed in, prompt the user for a movie file
  997.     if ((theMovie == NULL) && (theFSSpec == NULL)) {
  998.     
  999.         // display file-opening dialog box
  1000.         if (!GetFile(myPathName))
  1001.             goto bail;
  1002.  
  1003.         // add this document to the Documents list
  1004.         SHAddToRecentDocs(SHARD_PATH, myPathName);
  1005.  
  1006.         // get the movie file name from the full pathname
  1007.         GetDisplayName(myPathName, myFileName);
  1008.         
  1009.         // make an FSSpec record
  1010.         FSMakeFSSpec(0, 0L, c2pstr(myPathName), &myFSSpec);
  1011.     }
  1012.     
  1013.     // if we got an FSSpec passed in, copy it into myFSSpec
  1014.     if (theFSSpec != NULL) {
  1015.     
  1016.         // make an FSSpec record
  1017.         FSMakeFSSpec(theFSSpec->vRefNum, theFSSpec->parID, theFSSpec->name, &myFSSpec);    
  1018.     }
  1019.     
  1020.     // if we got no movie passed in, read one from the specified file
  1021.     if (theMovie == NULL) {
  1022.  
  1023.         // ideally, we'd like read and write permission, but we'll settle for read-only permission
  1024.         myErr = OpenMovieFile(&myFSSpec, &myRefNum, fsRdWrPerm);
  1025.         if (myErr != noErr)
  1026.             myErr = OpenMovieFile(&myFSSpec, &myRefNum, fsRdPerm);
  1027.  
  1028.         // if we couldn't open the file with even just read-only permission, bail....
  1029.         if (myErr != noErr)
  1030.             goto bail;
  1031.  
  1032.         // now fetch the first movie from the file
  1033.         myResID = 0;
  1034.         myErr = NewMovieFromFile(&myMovie, myRefNum, &myResID, NULL, newMovieActive, NULL);
  1035.         if (myErr != noErr)
  1036.             goto bail;
  1037.     
  1038.         // we will allow the user to edit our files, so we keep the movie file open
  1039.         // CloseMovieFile(myRefNum);
  1040.         
  1041.     } else {
  1042.         myMovie = theMovie;
  1043.     }
  1044.  
  1045.     //////////
  1046.     //
  1047.     // at this point, myMovie is an open movie, but myFSSpec may or may not be a valid FSSpec
  1048.     //
  1049.     //////////
  1050.     
  1051.     // set the default progress procedure for the movie
  1052.     SetMovieProgressProc(myMovie, (MovieProgressUPP)-1, 0);
  1053.         
  1054.     // create a new window to display the movie in
  1055.     gWeAreCreatingWindow = true;
  1056.     
  1057.     // create the child movie window
  1058.     myVersion = GetVersion();
  1059.     if ((myVersion < 0x80000000) || (LOBYTE(LOWORD(myVersion)) < 4)) {
  1060.         // this is Windows NT or Win32s, so use the WM_MDICREATE message
  1061.         MDICREATESTRUCT     mcs;
  1062.  
  1063.         mcs.szClass = gChildName;
  1064.         mcs.szTitle = myFileName;
  1065.         mcs.hOwner  = ghInst;
  1066.         mcs.x       = CW_USEDEFAULT;
  1067.         mcs.y       = CW_USEDEFAULT;
  1068.         mcs.cx      = CW_USEDEFAULT;
  1069.         mcs.cy      = CW_USEDEFAULT;
  1070.         mcs.style   = 0;
  1071.         mcs.lParam  = 0;
  1072.  
  1073.         myWindow = (HWND)SendMessage(ghWndMDIClient,
  1074.                                     WM_MDICREATE,
  1075.                                     0,
  1076.                                     (LPARAM)(LPMDICREATESTRUCT)&mcs);
  1077.     } else {
  1078.         // this method will only work with Windows 95, not Windows NT or Win32s
  1079.         myWindow = CreateWindowEx(WS_EX_MDICHILD,
  1080.                                    gChildName,
  1081.                                    myFileName,
  1082.                                    0,
  1083.                                    CW_USEDEFAULT,
  1084.                                    CW_USEDEFAULT,
  1085.                                    CW_USEDEFAULT,
  1086.                                    CW_USEDEFAULT,
  1087.                                    ghWndMDIClient, 
  1088.                                    NULL,
  1089.                                    ghInst,
  1090.                                    0);
  1091.     }
  1092.     
  1093.     gWeAreCreatingWindow = false;
  1094.     if (myWindow == NULL)
  1095.         goto bail;
  1096.  
  1097.     MacSetPort(GetPortFromWindowReference(myWindow));
  1098.     myWindowObject = GetWindowObjectFromWindow(myWindow);
  1099.     if (myWindowObject == NULL)
  1100.         goto bail;
  1101.  
  1102.     // set the window title
  1103.     SetWindowTitleFromFSSpec(myWindow, &myFSSpec, true);
  1104.  
  1105.     // make sure the movie uses the window GWorld in all situations
  1106.     SetMovieGWorld(myMovie, (CGrafPtr)GetPortFromWindowReference(myWindow), GetGWorldDevice((CGrafPtr)GetPortFromWindowReference(myWindow)));
  1107.  
  1108.     // create and configure the movie controller
  1109.     myMC = SetupMovieWindowWithController(myMovie, myWindow, true);
  1110.  
  1111.     // store movie info in the window record
  1112.     (**myWindowObject).fMovie = myMovie;
  1113.     (**myWindowObject).fController = myMC;
  1114.     (**myWindowObject).fFileResID = myResID;
  1115.     (**myWindowObject).fFileRefNum = myRefNum;
  1116.     (**myWindowObject).fCanResizeWindow = true;
  1117.     (**myWindowObject).fDirty = false;
  1118.     (**myWindowObject).fInstance = NULL;
  1119.     (**myWindowObject).fAppData = NULL;
  1120.     (**myWindowObject).fFileFSSpec = myFSSpec;
  1121.     
  1122.     // do any application-specific window object initialization
  1123.     InitApplicationWindowObject(myWindowObject);
  1124.     
  1125.     // size the window to fit the movie and controller
  1126.     SizeWindowToMovie(myWindowObject);
  1127.         
  1128.     // set the movie's play hints to allow dynamic resizing
  1129.     SetMoviePlayHints(myMovie, hintsAllowDynamicResize, hintsAllowDynamicResize);
  1130.  
  1131.     // show the window
  1132.     ShowWindow(myWindow, SW_SHOW);
  1133.     UpdateWindow(myWindow);
  1134.  
  1135.     // one more movie window has been opened
  1136.     gNumWindowsOpen++;
  1137.  
  1138.     // if the movie is a streamed movie, then start it playing immediately
  1139.     if (QTUtils_IsStreamedMovie(myMovie))
  1140.         MCDoAction(myMC, mcActionPrerollAndPlay, (void *)GetMoviePreferredRate(myMovie));
  1141.         
  1142.     return(true);
  1143.  
  1144. bail:
  1145.     if (myWindow != NULL)
  1146.         SendMessage(ghWndMDIClient, WM_MDIDESTROY, (WPARAM)myWindow, 0L);
  1147.         
  1148.     if (myMC != NULL)
  1149.         DisposeMovieController(myMC);
  1150.         
  1151.     if (myMovie != NULL)
  1152.         DisposeMovie(myMovie);
  1153.         
  1154.     if (myRefNum != 0)
  1155.         CloseMovieFile(myRefNum);
  1156.         
  1157.     MacSetPort(mySavedPort);    // restore the port that was active when this function was called
  1158.  
  1159.     return(false);
  1160. }
  1161.  
  1162.  
  1163. //////////
  1164. //
  1165. // DoSaveAsMovieFile
  1166. // Save the movie in the specified window under a new name.
  1167. //
  1168. // Human interface guidelines for "Save As..." dictate that, if the user selects a new file name
  1169. // for the current movie, then that new file shall become the active one. This means that we need
  1170. // to close the current movie file and open the new one.
  1171. //
  1172. //////////
  1173.  
  1174. OSErr DoSaveAsMovieFile (WindowReference theWindow)
  1175. {
  1176.     WindowObject        myWindowObject = NULL;
  1177.     Movie                 myMovie = NULL;
  1178.     StandardFileReply    mySFReply;
  1179.     StringPtr             myPrompt = QTUtils_ConvertCToPascalString(kSavePrompt);
  1180.     StringPtr             myFileName = QTUtils_ConvertCToPascalString(kSaveMovieFileName);
  1181.     OSErr                myErr = paramErr;
  1182.  
  1183.     // get the window object associated with the specified window
  1184.     myWindowObject = GetWindowObjectFromWindow(theWindow);
  1185.     if (myWindowObject == NULL)
  1186.         goto bail;
  1187.         
  1188.     myMovie = (**myWindowObject).fMovie;
  1189.     if (myMovie == NULL)
  1190.         goto bail;
  1191.         
  1192.     StandardPutFile(myPrompt, myFileName, &mySFReply); 
  1193.     if (mySFReply.sfGood) {
  1194.         Movie            myNewMovie = NULL;
  1195.         MovieController    myMC = NULL;
  1196.         long            myFlags;
  1197.         short            myRefNum = kInvalidFileRefNum;
  1198.         short            myResID = movieInDataForkResID;
  1199.         
  1200.         //////////
  1201.         //
  1202.         // we have a valid FSSpec for the new movie file; now we want to create a new movie file,
  1203.         // save the movie data into the new file, close the existing movie file, and then swap
  1204.         // the window object data
  1205.         //
  1206.         //////////
  1207.         
  1208.         // delete any existing file of that name
  1209.         if (mySFReply.sfReplacing) {
  1210.             myErr = DeleteMovieFile(&mySFReply.sfFile);
  1211.             if (myErr != noErr)
  1212.                 goto bail;
  1213.         }
  1214.         
  1215.         myFlags = createMovieFileDeleteCurFile | createMovieFileDontOpenFile | createMovieFileDontCreateMovie | createMovieFileDontCreateResFile;
  1216.         myErr = CreateMovieFile(&mySFReply.sfFile, FOUR_CHAR_CODE('TVOD'), smSystemScript, myFlags, NULL, NULL);
  1217.         if (myErr != noErr)
  1218.             goto bail;
  1219.         
  1220.         myErr = OpenMovieFile(&mySFReply.sfFile, &myRefNum, fsRdWrPerm);
  1221.         if (myErr != noErr)
  1222.             goto bail;
  1223.             
  1224.         // write existing movie's data into new movie file
  1225.         myErr = AddMovieResource(myMovie, myRefNum, &myResID, mySFReply.sfFile.name);
  1226.         if (myErr != noErr)
  1227.             goto bail;
  1228.  
  1229.         // get the new movie from the file
  1230.         myErr = NewMovieFromFile(&myNewMovie, myRefNum, &myResID, NULL, newMovieActive, NULL);        
  1231.         if (myErr != noErr)
  1232.             goto bail;
  1233.         
  1234.         // create a new movie controller
  1235.         myMC = SetupMovieWindowWithController(myNewMovie, theWindow, false);
  1236.         
  1237.         //////////
  1238.         //
  1239.         // if we got to here, we've successfully created a new movie file, and NewMovieFromFile has
  1240.         // returned the new movie to us; so we need to close down the current movie and install the
  1241.         // new movie in its place
  1242.         //
  1243.         //////////
  1244.         
  1245.         // close the existing movie file
  1246.         if ((**myWindowObject).fFileRefNum != kInvalidFileRefNum)
  1247.             CloseMovieFile((**myWindowObject).fFileRefNum);
  1248.         
  1249.         // dispose of the existing movie controller and movie resource
  1250.         DisposeMovieController((**myWindowObject).fController);
  1251.         DisposeMovie(myMovie);
  1252.         
  1253.         // keep track of the new info
  1254.         (**myWindowObject).fMovie = myNewMovie;
  1255.         (**myWindowObject).fController = myMC;
  1256.         (**myWindowObject).fFileFSSpec = mySFReply.sfFile;
  1257.         (**myWindowObject).fFileResID = myResID;
  1258.         (**myWindowObject).fFileRefNum = myRefNum;
  1259.         (**myWindowObject).fDirty = false;
  1260.  
  1261.         // make sure the movie uses the window GWorld in all situations
  1262.         SetMovieGWorld(myNewMovie, (CGrafPtr)GetPortFromWindowReference((**myWindowObject).fWindow), GetGWorldDevice((CGrafPtr)GetPortFromWindowReference((**myWindowObject).fWindow)));
  1263.         
  1264.         // set the window title
  1265.         SetWindowTitleFromFSSpec(theWindow, &mySFReply.sfFile, true);
  1266.     } else {
  1267.         myErr = userCanceledErr;
  1268.     }
  1269.  
  1270. bail:
  1271.     free(myPrompt);
  1272.     free(myFileName);
  1273.     
  1274.     return(myErr);
  1275. }
  1276.  
  1277.  
  1278. //////////
  1279. //
  1280. // DoUpdateMovieFile
  1281. // Update the file (if any) attached to the movie.
  1282. //
  1283. //////////
  1284.  
  1285. Boolean DoUpdateMovieFile (WindowReference theWindow)
  1286. {
  1287.     WindowObject        myWindowObject = NULL;
  1288.     Movie                 myMovie = NULL;
  1289.     OSErr                myErr = noErr;
  1290.     
  1291.     // get the window object associated with the specified window
  1292.     myWindowObject = GetWindowObjectFromWindow(theWindow);
  1293.     if (myWindowObject == NULL)
  1294.         return(false);
  1295.         
  1296.     myMovie = (**myWindowObject).fMovie;
  1297.     if (myMovie == NULL)
  1298.         return(false);
  1299.         
  1300.     // update the current volume setting
  1301.     QTUtils_UpdateMovieVolumeSetting(myMovie);
  1302.     
  1303.     if ((**myWindowObject).fFileRefNum == kInvalidFileRefNum)        // brand new movie, so no file attached to it
  1304.         myErr = DoSaveAsMovieFile(theWindow);
  1305.     else                                                            // we have an existing file; just update the movie resource
  1306.         myErr = UpdateMovieResource(myMovie, (**myWindowObject).fFileRefNum, (**myWindowObject).fFileResID, NULL);
  1307.     
  1308.     (**myWindowObject).fDirty = false;
  1309.  
  1310.     return(myErr == noErr);
  1311. }
  1312.  
  1313.  
  1314. //////////
  1315. //
  1316. // DoCut
  1317. // Cut a movie segment.
  1318. //
  1319. //////////
  1320.  
  1321. static void DoCut (HWND theWnd)
  1322. {
  1323.     MovieController        myMC = NULL;
  1324.     WindowObject        myWindowObject = NULL;
  1325.     
  1326.     // get the window object associated with the specified window
  1327.     myWindowObject = GetWindowObjectFromWindow(theWnd);
  1328.     if (myWindowObject == NULL)
  1329.         return;
  1330.  
  1331.     myMC = (**myWindowObject).fController;
  1332.     if (myMC != NULL) {
  1333.         Movie            myMovie;
  1334.         
  1335.         myMovie = MCCut(myMC);                // cut the segment
  1336.         if (myMovie != NULL) {
  1337.             PutMovieOnScrap(myMovie, 0L);    // place the segment into the scrap
  1338.             DisposeMovie(myMovie);
  1339.         }
  1340.         
  1341.         (**myWindowObject).fDirty = true;
  1342.     }
  1343. }
  1344.  
  1345.  
  1346. //////////
  1347. //
  1348. // DoCopy
  1349. // Copy a movie segment.
  1350. //
  1351. //////////
  1352.  
  1353. static void DoCopy (HWND theWnd)
  1354. {
  1355.     MovieController        myMC = NULL;
  1356.     WindowObject        myWindowObject = NULL;
  1357.     
  1358.     // get the window object associated with the specified window
  1359.     myWindowObject = GetWindowObjectFromWindow(theWnd);
  1360.     if (myWindowObject == NULL)
  1361.         return;
  1362.  
  1363.     myMC = (**myWindowObject).fController;
  1364.     if (myMC != NULL) {
  1365.         Movie            myMovie;
  1366.         
  1367.         myMovie = MCCopy(myMC);                // copy the segment
  1368.         if (myMovie != NULL) {
  1369.             PutMovieOnScrap(myMovie, 0L);    // place the segment into the scrap
  1370.             DisposeMovie(myMovie);
  1371.         }
  1372.     }
  1373. }
  1374.  
  1375.  
  1376. //////////
  1377. //
  1378. // DoPaste
  1379. // Paste a movie segment.
  1380. //
  1381. //////////
  1382.  
  1383. static void DoPaste (HWND theWnd)
  1384. {
  1385.     MovieController        myMC = NULL;
  1386.     WindowObject        myWindowObject = NULL;
  1387.     
  1388.     // get the window object associated with the specified window
  1389.     myWindowObject = GetWindowObjectFromWindow(theWnd);
  1390.     if (myWindowObject == NULL)
  1391.         return;
  1392.  
  1393.     myMC = (**myWindowObject).fController;
  1394.     if (myMC != NULL) {
  1395.         MCPaste(myMC, NULL);
  1396.         (**myWindowObject).fDirty = true;
  1397.     }
  1398. }
  1399.  
  1400.  
  1401. //////////
  1402. //
  1403. // DoClear
  1404. // Clear a movie segment.
  1405. //
  1406. //////////
  1407.  
  1408. static void DoClear (HWND theWnd)
  1409. {
  1410.     MovieController        myMC = NULL;
  1411.     WindowObject        myWindowObject = NULL;
  1412.     
  1413.     // get the window object associated with the specified window
  1414.     myWindowObject = GetWindowObjectFromWindow(theWnd);
  1415.     if (myWindowObject == NULL)
  1416.         return;
  1417.  
  1418.     myMC = (**myWindowObject).fController;
  1419.     if (myMC != NULL) {
  1420.         MCClear(myMC);
  1421.         (**myWindowObject).fDirty = true;
  1422.     }
  1423. }
  1424.  
  1425.  
  1426. //////////
  1427. //
  1428. // DoUndo
  1429. // Undo an editing operation.
  1430. //
  1431. //////////
  1432.  
  1433. static void DoUndo (HWND theWnd)
  1434. {
  1435.     MovieController        myMC = NULL;
  1436.     WindowObject        myWindowObject = NULL;
  1437.     
  1438.     // get the window object associated with the specified window
  1439.     myWindowObject = GetWindowObjectFromWindow(theWnd);
  1440.     if (myWindowObject == NULL)
  1441.         return;
  1442.  
  1443.     myMC = (**myWindowObject).fController;
  1444.     if (myMC != NULL) {
  1445.         MCUndo(myMC);
  1446.         (**myWindowObject).fDirty = true;
  1447.     }
  1448. }
  1449.  
  1450.  
  1451. //////////
  1452. //
  1453. // GetDisplayName
  1454. // Given a full pathname, return the part that trails the rightmost path separator,
  1455. // in long file name format (not in 8.3 format).
  1456. //
  1457. //////////
  1458.  
  1459. static void GetDisplayName (char *thePathName, char *theDispName)
  1460. {
  1461.     SHFILEINFO            myFileInfo;
  1462.     DWORD                myResult;
  1463.     
  1464.     myResult = SHGetFileInfo(thePathName, (DWORD)0, &myFileInfo, sizeof(myFileInfo), SHGFI_DISPLAYNAME);
  1465.     if (myResult != 0) {
  1466.         // SHGetFileInfo successful
  1467.         strcpy(theDispName, myFileInfo.szDisplayName);
  1468.     } else {
  1469.         // SHGetFileInfo not successful, so find the basename ourselves
  1470.         short    myLength = 0;
  1471.         short    myIndex;
  1472.  
  1473.         // get the length of the pathname
  1474.         myLength = strlen(thePathName);
  1475.         
  1476.         // find the position of the rightmost path separator in thePathName
  1477.         if (strchr(thePathName, kWinFilePathSeparator) != NULL) {
  1478.     
  1479.             myIndex = myLength - 1;
  1480.             while (thePathName[myIndex] != kWinFilePathSeparator)
  1481.                 myIndex--;
  1482.                 
  1483.             // calculate the length of the basename
  1484.             myLength = myLength - myIndex - 1;
  1485.     
  1486.         } else {
  1487.             // there is no rightmost path separator in thePathName;
  1488.             // set myIndex so that myIndex + 1 == 0, for the call to BlockMove below
  1489.             myIndex = -1;
  1490.         }
  1491.         
  1492.         // copy into theDispName the substring of thePathName from myIndex + 1 to the end
  1493.         BlockMove(&thePathName[myIndex + 1], theDispName, myLength);
  1494.         theDispName[myLength] = '\0';
  1495.     }
  1496. }
  1497.  
  1498.  
  1499. //////////
  1500. //
  1501. // SizeWindowToMovie
  1502. // Set the window size to exactly fit the movie and controller (if visible).
  1503. //
  1504. //////////
  1505.  
  1506. void SizeWindowToMovie (WindowObject theWindowObject)
  1507. {
  1508.     Rect                myMovieBounds;
  1509.     MovieController        myMC = NULL;
  1510.     Movie                myMovie = NULL;
  1511.  
  1512.     gWeAreSizingWindow = true;
  1513.  
  1514.     if (theWindowObject == NULL)
  1515.         goto bail;
  1516.     
  1517.     myMC = (**theWindowObject).fController;
  1518.     myMovie = (**theWindowObject).fMovie;
  1519.  
  1520.     if (MCGetVisible(myMC))
  1521.         MCGetControllerBoundsRect(myMC, &myMovieBounds);
  1522.     else
  1523.         GetMovieBox(myMovie, &myMovieBounds);
  1524.     
  1525.     // make sure that the movie has a non-zero width;
  1526.     // a zero height is okay (for example, with a music movie with no controller bar)
  1527.     if (myMovieBounds.right - myMovieBounds.left == 0) {
  1528.         myMovieBounds.left = 0;
  1529.         myMovieBounds.right = GetWindowWidth((**theWindowObject).fWindow);
  1530.     }
  1531.     
  1532.     SizeWindow(GetPortFromWindowReference((**theWindowObject).fWindow),
  1533.                                             myMovieBounds.right - myMovieBounds.left,
  1534.                                             myMovieBounds.bottom - myMovieBounds.top,
  1535.                                             true);
  1536.  
  1537. bail:                                                
  1538.     gWeAreSizingWindow = false;
  1539. }
  1540.  
  1541.  
  1542. //////////
  1543. //
  1544. // ShowAboutBox 
  1545. // Display and manage the About dialog box.
  1546. //
  1547. //////////
  1548.  
  1549. static void ShowAboutBox (void)
  1550. {
  1551.     DialogBox(ghInst, MAKEINTRESOURCE(IDD_ABOUT), ghWnd, (DLGPROC)DialogProc);
  1552. }
  1553.  
  1554.  
  1555. //////////
  1556. //
  1557. // DoCautionAlert 
  1558. // Display and manage a caution alert.
  1559. //
  1560. // Based on ShowUserMessage by Stephen Chernicoff, in his WiniEdit application
  1561. // (as described in the book "From Mac to Windows" on CodeWarrior reference CD).
  1562. //
  1563. //////////
  1564.  
  1565. int DoCautionAlert (HWND theWnd, UINT theID, UINT theIconStyle, UINT theButtonStyle, LPSTR theTitle, LPSTR theArgument)
  1566. {
  1567.     char            myTemplate[kAlertMessageMaxLength];
  1568.     char            myText[kAlertMessageMaxLength];
  1569.     UINT            myStyle;
  1570.     int                myItem;
  1571.     
  1572.     // beep, to get the user's attention (just like CautionAlert on MacOS)
  1573.     DoBeep();
  1574.     
  1575.     // load the message text template from a resource
  1576.     LoadString(ghInst, theID, myTemplate, sizeof(myTemplate));
  1577.     
  1578.     // insert argument into the message text template, to get the message text
  1579.     wsprintf(myText, myTemplate, theArgument);
  1580.     
  1581.     // set the dialog box style
  1582.     myStyle = theIconStyle | theButtonStyle | MB_APPLMODAL | MB_SETFOREGROUND;
  1583.  
  1584.     // display the dialog box
  1585.     myItem = MessageBox(theWnd, myText, theTitle, myStyle);
  1586.     
  1587.     return(myItem);
  1588. }
  1589.  
  1590.  
  1591. //////////
  1592. //
  1593. // DialogProc 
  1594. // Dialog callback procedure.
  1595. //
  1596. //////////
  1597.  
  1598. static UINT APIENTRY DialogProc (HWND theDialog, UINT theMessage, WPARAM wParam, LPARAM lParam)
  1599. {
  1600.     BOOL    isHandled = false;
  1601.  
  1602.     switch (theMessage) {
  1603.     
  1604.         case WM_INITDIALOG: {
  1605.             Point            myPoint;
  1606.             long            myWidth;
  1607.             long            myHeight;
  1608.             RECT            myRect;
  1609.             RECT            myDeskRect;
  1610.             HWND            myWindow;
  1611.             OPENFILENAME    *myOFNPtr = (OPENFILENAME *)lParam;
  1612.             
  1613.             myWindow = theDialog;
  1614.                 
  1615.             // check whether theDialog is the Open File common dialog box
  1616.             
  1617.             // we need to do this because, for the Open File dialog box, theDialog isn't
  1618.             // the actual visible dialog box, but an invisible child of the visible dialog box;
  1619.             // for WM_INITDIALOG, lParam is the address of the structure passed to GetOpenFileName,
  1620.             // so we can just look for the value we previously put into the lCustData field
  1621.             // to make sure that we've got the correct dialog.
  1622.             if (myOFNPtr != NULL)
  1623.                 if (myOFNPtr->lCustData == kOpenDialogCustomData)
  1624.                     myWindow = GetParent(theDialog);
  1625.                 
  1626.             // center the dialog window on the screen
  1627.             GetWindowRect(myWindow, &myRect);
  1628.             myWidth = myRect.right - myRect.left;
  1629.             myHeight = myRect.bottom - myRect.top;
  1630.             GetWindowRect(GetDesktopWindow(), &myDeskRect);
  1631.             myPoint.h = (short)((myDeskRect.right + myDeskRect.left)/2 - myWidth/2);
  1632.             myPoint.v = (short)((myDeskRect.top + myDeskRect.bottom)/3 - myHeight/3);
  1633.             SetWindowPos(myWindow, 0, myPoint.h, myPoint.v, 0, 0, SWP_NOZORDER | SWP_NOSIZE);
  1634.             
  1635.             // let Windows set the input focus
  1636.             isHandled = true;
  1637.             break;
  1638.         }
  1639.         
  1640.         case WM_CLOSE:
  1641.             EndDialog(theDialog, IDOK);
  1642.             isHandled = true;
  1643.             break;
  1644.         
  1645.         case WM_COMMAND:
  1646.             switch (LOWORD(wParam)) {
  1647.                 case IDOK:
  1648.                     EndDialog(theDialog, IDOK);
  1649.                     isHandled = true;
  1650.                     break;
  1651.                 default:
  1652.                     isHandled = false;
  1653.                     break;
  1654.             }
  1655.             break;
  1656.         
  1657.         default:
  1658.             isHandled = false;
  1659.             break;
  1660.     }
  1661.  
  1662.     return(isHandled);
  1663. }
  1664.  
  1665.  
  1666. //////////
  1667. //
  1668. // CalcWindowMinMaxInfo 
  1669. // Get minimum and maximum possible size of this window.
  1670. //
  1671. //////////
  1672.  
  1673. static void CalcWindowMinMaxInfo (HWND theWnd, LPMINMAXINFO lpMinMax)
  1674. {
  1675.     WindowObject        myWindowObject = NULL;
  1676.     MovieController        myMC = NULL;
  1677.     Movie                myMovie = NULL;
  1678.  
  1679.     myWindowObject = GetWindowObjectFromWindow(theWnd);
  1680.     if (myWindowObject != NULL) {
  1681.         myMC = (**myWindowObject).fController;
  1682.         myMovie = (**myWindowObject).fMovie;
  1683.     }
  1684.  
  1685.     if (myMC && myMovie) {
  1686.         Rect            myMovieBox;
  1687.         short            myControllerHeight = 0;                    // assume there's no controller bar
  1688.         
  1689.         if (MCGetVisible(myMC))
  1690.             myControllerHeight = QTUtils_GetControllerBarHeight(myMC);
  1691.  
  1692.         lpMinMax->ptMinTrackSize.x = gMCResizeBounds.left + (2 * GetSystemMetrics(SM_CXFRAME));
  1693.         
  1694.         GetMovieBox(myMovie, &myMovieBox);
  1695.         if (myMovieBox.bottom - myMovieBox.top != 0)
  1696.             lpMinMax->ptMinTrackSize.y = 
  1697.                 gMCResizeBounds.top +                            // growbounds height +
  1698.                 (2 * GetSystemMetrics(SM_CXFRAME)) +            // frame thickness +
  1699.                 GetSystemMetrics(SM_CYCAPTION) +                // caption height +
  1700.                 -1 +                                            // fudge factor +
  1701.                 myControllerHeight;                                // movie controller bar height
  1702.         else
  1703.             lpMinMax->ptMaxSize.y =
  1704.             lpMinMax->ptMaxTrackSize.y =
  1705.             lpMinMax->ptMinTrackSize.y = 
  1706.                 0 +                                                // height of audio only movie +
  1707.                 (2 * GetSystemMetrics(SM_CXFRAME)) +            // frame thickness +
  1708.                 GetSystemMetrics(SM_CYCAPTION) +                // caption height +
  1709.                 -1 +                                            // fudge factor +
  1710.                 myControllerHeight;                                // movie controller bar height
  1711.     }
  1712. }
  1713.  
  1714.  
  1715. //////////
  1716. //
  1717. // SetWindowTitleFromFSSpec
  1718. // Set the title of the specified window, using the name contained in the specified FSSpec.
  1719. //
  1720. //////////
  1721.  
  1722. static void SetWindowTitleFromFSSpec (HWND theWnd, FSSpec *theFSSpec, Boolean theAddToRecentDocs)
  1723. {
  1724.     char    *myTempName;
  1725.     char    myWindName[MAX_PATH];
  1726.  
  1727.     // get the full pathname contained in the FSSpec (which is a Str255)
  1728.     myTempName = QTUtils_ConvertPascalToCString(theFSSpec->name);
  1729.  
  1730.     // get the movie file name from the full pathname
  1731.     GetDisplayName(myTempName, myWindName);
  1732.  
  1733.     // set the window title
  1734.     SetWindowText(theWnd, myWindName);
  1735.     
  1736.     if (theAddToRecentDocs) {
  1737.         // add this document to the Documents list
  1738.         SHAddToRecentDocs(SHARD_PATH, myTempName);
  1739.     }
  1740.     
  1741.     free(myTempName);
  1742. }
  1743.  
  1744.  
  1745. ///////////////////////////////////////////////////////////////////////////////////////////////////////////
  1746. //
  1747. // Window walking utilities.
  1748. //
  1749. // Use these two functions to iterate through all open movie windows belonging to the application.
  1750. //
  1751. ///////////////////////////////////////////////////////////////////////////////////////////////////////////
  1752.  
  1753. //////////
  1754. //
  1755. // GetFrontMovieWindow
  1756. // Return a reference to the frontmost movie window.
  1757. //
  1758. //////////
  1759.  
  1760. WindowReference GetFrontMovieWindow (void)
  1761. {
  1762.     return(GetWindow(ghWndMDIClient, GW_CHILD));
  1763. }
  1764.  
  1765.  
  1766. //////////
  1767. //
  1768. // GetNextMovieWindow
  1769. // Return a reference to the next movie window.
  1770. //
  1771. //////////
  1772.  
  1773. WindowReference GetNextMovieWindow (WindowReference theWindow)
  1774. {
  1775.     return(GetWindow(theWindow, GW_HWNDNEXT));
  1776. }
  1777.  
  1778.  
  1779. ///////////////////////////////////////////////////////////////////////////////////////////////////////////
  1780. //
  1781. // Data retrieval utilities.
  1782. //
  1783. // Use the following functions to retrieve the window object, the application-specific data, or the movie
  1784. // controller that is associated with a window.
  1785. //
  1786. ///////////////////////////////////////////////////////////////////////////////////////////////////////////
  1787.  
  1788. //////////
  1789. //
  1790. // GetWindowObjectFromFrontWindow
  1791. // Get the window object associated with the frontmost child window.
  1792. //
  1793. //////////
  1794.  
  1795. WindowObject GetWindowObjectFromFrontWindow (void)
  1796. {
  1797.     HWND               myChild;
  1798.  
  1799.     myChild = (HWND)SendMessage(ghWndMDIClient, WM_MDIGETACTIVE, 0, 0L);
  1800.     return(GetWindowObjectFromWindow(myChild));
  1801. }
  1802.  
  1803.  
  1804. //////////
  1805. //
  1806. // GetWindowObjectFromWindow
  1807. // Get the window object associated with the specified window.
  1808. //
  1809. //////////
  1810.  
  1811. WindowObject GetWindowObjectFromWindow (WindowReference theWnd)
  1812. {
  1813.     WindowObject        myWindowObject;
  1814.  
  1815.     if (theWnd == NULL)
  1816.         return(NULL);
  1817.                 
  1818.     myWindowObject = (WindowObject)GetWindowLong(theWnd, GWL_USERDATA);
  1819.  
  1820.     // make sure this is a window object
  1821.     if (!IsWindowObjectOurs(myWindowObject))
  1822.         return(NULL);
  1823.         
  1824.     return(myWindowObject);
  1825. }
  1826.  
  1827.  
  1828. //////////
  1829. //
  1830. // GetMCFromFrontWindow
  1831. // Get the movie controller (if any) associated with the frontmost child window.
  1832. //
  1833. //////////
  1834.  
  1835. MovieController GetMCFromFrontWindow (void)
  1836. {
  1837.     MovieController     myMC = NULL;
  1838.     WindowObject        myWindowObject = NULL;
  1839.         
  1840.     myWindowObject = GetWindowObjectFromFrontWindow();
  1841.     if (myWindowObject != NULL)
  1842.         myMC = (**myWindowObject).fController;
  1843.         
  1844.     return(myMC);
  1845. }
  1846.  
  1847.  
  1848. //////////
  1849. //
  1850. // GetMCFromWindow
  1851. // Get the movie controller (if any) associated with the specified window.
  1852. //
  1853. //////////
  1854.  
  1855. MovieController GetMCFromWindow (WindowReference theWindow)
  1856. {
  1857.     MovieController     myMC = NULL;
  1858.     WindowObject        myWindowObject = NULL;
  1859.         
  1860.     myWindowObject = GetWindowObjectFromWindow(theWindow);
  1861.     if (myWindowObject != NULL)
  1862.         myMC = (**myWindowObject).fController;
  1863.         
  1864.     return(myMC);
  1865. }
  1866.  
  1867.  
  1868. //////////
  1869. //
  1870. // GetQTVRInstanceFromFrontWindow
  1871. // Get the QTVRInstance (if any) associated with the frontmost child window.
  1872. //
  1873. //////////
  1874.  
  1875. QTVRInstance GetQTVRInstanceFromFrontWindow (void)
  1876. {
  1877.     QTVRInstance         myInstance = NULL;
  1878.     WindowObject        myWindowObject = NULL;
  1879.  
  1880.     myWindowObject = GetWindowObjectFromFrontWindow();
  1881.     if (myWindowObject != NULL)
  1882.         myInstance = (**myWindowObject).fInstance;
  1883.         
  1884.     return(myInstance);
  1885. }
  1886.  
  1887.  
  1888. //////////
  1889. //
  1890. // GetAppDataFromFrontWindow
  1891. // Get the application-specific data associated with the frontmost child window.
  1892. //
  1893. //////////
  1894.  
  1895. Handle GetAppDataFromFrontWindow (void)
  1896. {
  1897.     HWND               myChild;
  1898.  
  1899.     myChild = (HWND)SendMessage(ghWndMDIClient, WM_MDIGETACTIVE, 0, 0L);
  1900.     return(GetAppDataFromWindow(myChild));
  1901. }
  1902.  
  1903.  
  1904. //////////
  1905. //
  1906. // GetAppDataFromWindow
  1907. // Get the application-specific data associated with the specified window.
  1908. //
  1909. //////////
  1910.  
  1911. Handle GetAppDataFromWindow (WindowReference theWnd)
  1912. {
  1913.     WindowObject        myWindowObject = NULL;
  1914.     
  1915.     myWindowObject = GetWindowObjectFromWindow(theWnd);
  1916.     if (myWindowObject == NULL)
  1917.         return(NULL);
  1918.     else
  1919.         return(GetAppDataFromWindowObject(myWindowObject));
  1920. }
  1921.  
  1922.  
  1923. //////////
  1924. //
  1925. // GetAppDataFromWindowObject
  1926. // Get the application-specific data associated with the specified window object.
  1927. //
  1928. //////////
  1929.  
  1930. Handle GetAppDataFromWindowObject (WindowObject theWindowObject)
  1931. {
  1932.     Handle                myAppData = NULL;
  1933.             
  1934.     // make sure this is a window object belonging to our application
  1935.     if (!IsWindowObjectOurs(theWindowObject))
  1936.         return(myAppData);
  1937.     
  1938.     // get the app data handle from the window object
  1939.     myAppData = (**theWindowObject).fAppData;
  1940.     
  1941.     return(myAppData);
  1942. }
  1943.  
  1944.  
  1945. //////////
  1946. //
  1947. // IsWindowObjectOurs
  1948. // Does the specified window object belong to our application?
  1949. //
  1950. //////////
  1951.  
  1952. Boolean IsWindowObjectOurs (WindowObject theWindowObject)
  1953. {
  1954.     OSType        myType = 0;
  1955.  
  1956.     if ((theWindowObject == NULL) || (*theWindowObject == NULL))
  1957.         return(false);
  1958.         
  1959.     myType = (**theWindowObject).fObjectType;
  1960.     if (myType == kMovieControllerObject)
  1961.         return(true);
  1962.     else
  1963.         return(false);
  1964. }
  1965.  
  1966.  
  1967. ///////////////////////////////////////////////////////////////////////////////////////////////////////////
  1968. //
  1969. // Miscellaneous utilities.
  1970. //
  1971. // Use the following functions to play beeps, manipulate menus, and do other miscellaneous things. These
  1972. // functions are intended for use in cross-platform code.
  1973. //
  1974. ///////////////////////////////////////////////////////////////////////////////////////////////////////////
  1975.  
  1976. //////////
  1977. //
  1978. // DoBeep
  1979. // Beep.
  1980. //
  1981. //////////
  1982.  
  1983. void DoBeep (void)
  1984. {
  1985.     MessageBeep(MB_OK);
  1986. }
  1987.  
  1988.  
  1989. //////////
  1990. //
  1991. // SetMenuState
  1992. // Set the enabled/disabled state of a menu.
  1993. //
  1994. //////////
  1995.  
  1996. void SetMenuState (MenuReference theMenu, UInt16 theMenuRank, short theState)
  1997. {
  1998.     SetMenuItemState(theMenu, theMenuRank, theState | MF_BYPOSITION);
  1999. }
  2000.  
  2001.  
  2002. //////////
  2003. //
  2004. // SetMenuItemState
  2005. // Set the enabled/disabled state of a menu item.
  2006. //
  2007. //////////
  2008.  
  2009. void SetMenuItemState (MenuReference theMenu, UInt16 theMenuItem, short theState)
  2010. {
  2011.     EnableMenuItem(theMenu, (UINT)theMenuItem, (UINT)theState);
  2012. }
  2013.  
  2014.  
  2015. //////////
  2016. //
  2017. // SetMenuItemLabel
  2018. // Set the label (that is, the text) of a menu item.
  2019. //
  2020. //////////
  2021.  
  2022. void SetMenuItemLabel (MenuReference theMenu, UInt16 theMenuItem, char *theText)
  2023. {
  2024.     ModifyMenu(theMenu, (UINT)theMenuItem, MF_BYCOMMAND | MF_STRING, (UINT)theMenuItem, (LPSTR)theText);
  2025. }
  2026.  
  2027.  
  2028. //////////
  2029. //
  2030. // SetMenuItemCheck
  2031. // Set the check mark state state of a menu item.
  2032. //
  2033. //////////
  2034.  
  2035. void SetMenuItemCheck (MenuReference theMenu, UInt16 theMenuItem, Boolean theState)
  2036. {
  2037.     CheckMenuItem(theMenu, (UINT)theMenuItem, theState ? MF_CHECKED : MF_UNCHECKED);
  2038. }
  2039.  
  2040.  
  2041. //////////
  2042. //
  2043. // GetPortFromWindowReference 
  2044. // Return the graphics port associated with a window reference.
  2045. //
  2046. //////////
  2047.  
  2048. GrafPtr GetPortFromWindowReference (WindowReference theWindow)
  2049. {
  2050.     GrafPtr        myPort = NULL;
  2051.     
  2052.     if (theWindow != NULL)
  2053.         myPort = (GrafPtr)GetHWNDPort(theWindow);
  2054.     
  2055.     return(myPort);
  2056. }
  2057.  
  2058.  
  2059. //////////
  2060. //
  2061. // GetWindowReferenceFromPort
  2062. // Return the window reference associated with a graphics port.
  2063. //
  2064. //////////
  2065.  
  2066. WindowReference GetWindowReferenceFromPort (GrafPtr thePort)
  2067. {
  2068.     WindowReference        myWindow = NULL;
  2069.     
  2070.     if (thePort != NULL)
  2071.         myWindow = (WindowReference)GetPortHWND(thePort);
  2072.     
  2073.     return(myWindow);
  2074. }
  2075.  
  2076.  
  2077. //////////
  2078. //
  2079. // GetWindowWidth
  2080. // Return the width of the specified window.
  2081. //
  2082. //////////
  2083.  
  2084. short GetWindowWidth (WindowReference theWindow)
  2085. {
  2086.     short        myWidth = 0;
  2087.     RECT        myRect;
  2088.     
  2089.     if (theWindow != NULL)
  2090.         if (GetWindowRect(theWindow, &myRect))
  2091.             myWidth = myRect.right - myRect.left;
  2092.  
  2093.     return(myWidth);
  2094. }
  2095.  
  2096.  
  2097. //////////
  2098. //
  2099. // GetFrontAppWindow
  2100. // Return a reference to the frontmost window (whether or not it's a movie window).
  2101. //
  2102. //////////
  2103.  
  2104. WindowReference GetFrontAppWindow (void)
  2105. {
  2106.     return(GetWindow(ghWnd, GW_HWNDFIRST));
  2107. }
  2108.  
  2109.  
  2110. //////////
  2111. //
  2112. // GetNextAppWindow
  2113. // Return a reference to the next window (whether or not it's a movie window).
  2114. //
  2115. //////////
  2116.  
  2117. WindowReference GetNextAppWindow (WindowReference theWindow)
  2118. {
  2119.     return(GetWindow(theWindow, GW_HWNDNEXT));
  2120. }
  2121.